import sys
import json
import socket
import selectors

from .handle import Request
from .process import Process


class Server:
    ENCODING = "utf-8"
    BUFFER_SIZE = 4096

    def __init__(self, host="127.0.0.1", port=9999):
        self.addr = (host, port)
        self.server = socket.socket()
        self.selector = selectors.DefaultSelector()
        self.server.bind(self.addr)
        self.server.listen()
        self.server.setblocking(False)
        self.selector.register(self.server, selectors.EVENT_READ, self.accept)

    def accept(self, *args):
        new_sock, raddr = self.server.accept()
        print("{} has connected".format(raddr))
        self.selector.register(new_sock, selectors.EVENT_READ, self.handle)

    def handle(self, key: selectors.SelectorKey, mask):
        sock: socket.socket = getattr(key, "fileobj")
        self._handle(sock, key, mask)

    def _handle(self, sock: socket.socket, key, mask):
        data = bytearray()
        flag = True
        while flag:
            msg = sock.recv(self.BUFFER_SIZE)
            if len(msg) < self.BUFFER_SIZE:
                flag = False
            if msg:
                data.extend(msg)
            else:
                flag = False
        if data:
            data = bytes(data)
            data = data.decode(self.ENCODING)
            data = json.loads(data)

            p = Process(Request(data, sock, key, mask))
            p.run()
        else:
            print("{} has closed".format(sock.getpeername()))
            self.selector.unregister(sock)

    def run(self):
        print("server listen on {}".format(self.addr))
        while True:
            events = self.selector.select()
            for key, mask in events:
                key.data(key, mask)


if __name__ == '__main__':
    server = Server()
    server.run()
